package org.dev.vlp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.util.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dev.vlp.constants.EnumMomentType;
import org.dev.vlp.constants.HtmlTemplateConstant;
import org.dev.vlp.dto.PublishMomentParam;
import org.dev.vlp.entity.*;
import org.dev.vlp.exception.ApiException;
import org.dev.vlp.mapper.*;
import org.dev.vlp.service.MomentService;
import org.dev.vlp.utils.*;
import org.dev.vlp.vo.MomentVo;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author 86184
* @description 针对表【vlp_moment(动态表)】的数据库操作Service实现
* @createDate 2023-01-10 13:11:59
*/
@Service
@Slf4j
public class MomentServiceImpl extends ServiceImpl<MomentMapper, Moment>
    implements MomentService{

    @Autowired
    private TopicMapper topicMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MomentMapper momentMapper;

    @Autowired
    private MomentImageMapper momentImageMapper;

    @Autowired
    private TopicRelationMapper topicRelationMapper;

    @Autowired
    private ComUserMapper comUserMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void publishMoment(PublishMomentParam publishMoment, int userId) {

        // 查看是否已经加入社区
        int comId=publishMoment.getCommunityId();
        QueryWrapper<ComUser> comUserQueryWrapper = new QueryWrapper<>();
        comUserQueryWrapper.eq("user_id",userId).eq("com_id",comId);
        ComUser comUser = comUserMapper.selectOne(comUserQueryWrapper);
        AssertUtils.notNull(comUser,"未加入该社区");

//        EnumMomentType momentType = publishMoment.getType();
        Set<Long> topicIdSet = new HashSet<>();
        Set<Long> atUserIdList = new HashSet<>();
        String newTextContent = handlePublishMomentTextContent(userId, publishMoment.getContent(), topicIdSet, atUserIdList);

        Moment momentDBO = new Moment();
        momentDBO.setUserId((long)userId);
        momentDBO.setContent(newTextContent);
        momentDBO.setCommunityId(comId);
        momentMapper.insert(momentDBO);

        Long momentId = momentDBO.getMomentId();
        List<PublishMomentParam.Image> imageList = publishMoment.getImageList();
        if (!CollectionUtils.isEmpty(imageList)) {
            // 图文
            List<MomentImage> momentImageDBOList = imageList.stream().map(image -> new MomentImage(momentId, image.getUrl(), image.getWidth(), image.getHeight())).collect(Collectors.toList());
            momentImageMapper.insertBatchSomeColumn(momentImageDBOList);
        }

        if (!CollectionUtils.isEmpty(topicIdSet)) {
            List<TopicRelation> dboList = new ArrayList<>();
            topicIdSet.forEach(topicId -> {
                TopicRelation dbo = new TopicRelation();
                dbo.setTopicId(topicId);
                dbo.setMomentId(momentId);
                dbo.setGmtCreate(new Date());
                dbo.setGmtModified(new Date());
                dbo.setIsDeleted(0);
                dboList.add(dbo);
            });
            topicRelationMapper.insertBatchSomeColumn(dboList);
        }

        // @用户
//        if (CollectionUtils.isNotEmpty(atUserIdList)) {
//            // 发通知
//            atUserIdList.forEach(atUserId -> {
//                notificationService.sendNotification(NotificationDBO.builder()
//                        .type(EnumNotificationType.AT_ON_MOMENT.getValue())
//                        .momentId(momentId)
//                        .receiveUserId(atUserId)
//                        .build());
//            });
//        }
    }

    @Override
    public PageResult queryTopicMoment(int topicId, int pageSize, int page) {
        List<MomentVo> topicMoment = momentMapper.getTopicMoment(topicId, pageSize, (page - 1) * pageSize);
        QueryWrapper<TopicRelation> topicRelationQueryWrapper = new QueryWrapper<>();
        topicRelationQueryWrapper.eq("topic_id",topicId).eq("is_deleted",0);
        Long aLong = topicRelationMapper.selectCount(topicRelationQueryWrapper);
        return new PageResult(topicMoment,aLong,pageSize);
    }

    @Override
    public PageResult queryComMoment(int comId, int size, int page) {
        int start = PageUtils.getStart(page, size);
        QueryWrapper<Moment> momentQueryWrapper = new QueryWrapper<>();
        momentQueryWrapper.eq("is_deleted",0).eq("community_id",comId).last("limit "+String.valueOf(start)+","+String.valueOf(size));
        List<Moment> moments = momentMapper.selectList(momentQueryWrapper);
        Long aLong = momentMapper.selectCount(momentQueryWrapper);


        Set<Long> sendUserIdSet = moments.stream().map(Moment::getUserId).collect(Collectors.toSet());
        List<User> sendUserDBOList=new ArrayList<>();;
        if(!CollectionUtils.isEmpty(sendUserIdSet)) {
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.in("user_id", new ArrayList<>(sendUserIdSet)).eq("is_deleted", 0);
            sendUserDBOList = userMapper.selectList(userQueryWrapper);
        }
        Map<Long, User> idToUser = sendUserDBOList.stream().collect(Collectors.toMap(User::getUserId, Function.identity(), (key1, key2) -> key2));

        Set<Long> momentIdSet = moments.stream().map(Moment::getMomentId).collect(Collectors.toSet());
        List<MomentImage> momentImages=new ArrayList<>();;
        if(!CollectionUtils.isEmpty(momentIdSet)) {
            QueryWrapper<MomentImage> momentImageQueryWrapper = new QueryWrapper<>();
            momentImageQueryWrapper.select("moment_id,GROUP_CONCAT(url) as images").in("moment_id", momentIdSet).groupBy("moment_id");
            momentImages = momentImageMapper.selectList(momentImageQueryWrapper);
        }
        Map<Long, MomentImage> idToImage = momentImages.stream().collect(Collectors.toMap(MomentImage::getMomentId, Function.identity(), (key1, key2) -> key2));
//        System.out.println(idToImage);

        List<MomentVo> momentDTOList= BeanCopyUtils.copy(moments, MomentVo.class);
        momentDTOList.forEach(momentVo -> {
//            System.out.println(momentVo);
            User user = idToUser.get((long)momentVo.getUserId());

            momentVo.setUsername(user.getUsername());
            momentVo.setAvatar(user.getAvatar());
            System.out.println(momentVo);
            MomentImage momentImage = idToImage.get(momentVo.getMomentId());
            if(momentImage!=null){
                momentVo.setImages(momentImage.getImages());
            }
        });
        return new PageResult(momentDTOList,aLong,size);
    }

    @Override
    public MomentVo getMomentDetail(int momentId) {
        log.info("查看动态：" + momentId);

        MomentVo momentDTO = momentMapper.getMomentDetail(momentId);

        Long repostMomentId = momentDTO.getRepostMomentId();
        if (!Objects.equals(repostMomentId, 0L)) {
            // 转发动态
            MomentVo repostedMoment = momentMapper.getMomentDetail(repostMomentId.intValue());
            AssertUtils.notNull(repostedMoment, "moment不存在：" + momentId);

            momentDTO.setRepostedMoment(repostedMoment);
        }

        return momentDTO;
    }

    @Override
    public void deleteMoment(int momentId,int userId) {
        QueryWrapper<Moment> momentQueryWrapper = new QueryWrapper<>();
        momentQueryWrapper.eq("moment_id",momentId);
        Moment moment = momentMapper.selectOne(momentQueryWrapper);
        AssertUtils.notNull(moment, "moment不存在：" + momentId);
        if(moment.getUserId()!=userId){
            throw new ApiException("无权限删除");
        }
        moment.setIsDeleted(1);

        if(momentMapper.updateById(moment)<=0){
            throw new ApiException("删除失败");
        }
    }

    private String handlePublishMomentTextContent(int userId, String textContent, Set<Long> topicIdSet, Set<Long> atUserIdList) {
        // 处理话题
        Set<String> matchedTopicSet = new HashSet<>();
        textContent = ReplaceUtils.translate(textContent, HtmlTemplateConstant.TOPIC_TEMPLATE, HtmlTemplateConstant.TOPIC_PATTERN, new HashMap<>(), matchedTopicSet);
        Set<String> newMatchedTopicSet = new HashSet<>();
        matchedTopicSet.forEach(topicName -> {
            if (topicName.length() > 2) {
                String newTopicName = topicName.substring(1, topicName.length() - 1);
                newMatchedTopicSet.add(newTopicName);
            }
        });
        if (!CollectionUtils.isEmpty(newMatchedTopicSet)) {
            QueryWrapper<Topic> topicQueryWrapper = new QueryWrapper<>();
            topicQueryWrapper.in("name",newMatchedTopicSet);
            List<Topic> topicDBOList = topicMapper.selectList(topicQueryWrapper);
            // 更新
            if (!CollectionUtils.isEmpty(topicDBOList)) {
                topicDBOList.forEach(topic -> {
                    topic.setLastUpdateUserId((long)userId);
                    topicMapper.updateById(topic);
                });
                topicIdSet.addAll(topicDBOList.stream().map(Topic::getTopicId).collect(Collectors.toSet()));
            }
            // 插入
            Set<String> nameSet = topicDBOList.stream().map(Topic::getName).collect(Collectors.toSet());
            newMatchedTopicSet.removeAll(nameSet);
            if (!CollectionUtils.isEmpty(newMatchedTopicSet)) {
                List<Topic> dboList = new ArrayList<>();
                newMatchedTopicSet.forEach(topicName -> {
                    Topic dbo = new Topic();
                    dbo.setCreatorId((long)userId);
                    dbo.setLastUpdateUserId((long)userId);
                    dbo.setName(topicName);
                    dbo.setGmtCreate(new Date());
                    dbo.setGmtModified(new Date());
                    dbo.setIsDeleted(0);
//                    dbo.setCoverUrl(ossConfig.getDomainUrl() + UserContext.getLoginUser().getArtistName() + "/image/" + ImageGenerateUtils.getImageName());
                    dboList.add(dbo);
                });
                topicMapper.insertBatchSomeColumn(dboList);
                topicIdSet.addAll(dboList.stream().map(Topic::getTopicId).collect(Collectors.toSet()));
            }
        }

        // 处理@
        Set<String> matchedAtSet = new HashSet<>();
        Set<String> newMatchedAtSet = new HashSet<>();
        textContent = ReplaceUtils.translate(textContent, HtmlTemplateConstant.AT_TEMPLATE, HtmlTemplateConstant.AT_PATTERN, new HashMap<>(), matchedAtSet);
        matchedAtSet.forEach(userName -> {
            if (userName.length() > 1) {
                String newUserName = userName.substring(1);
                newMatchedAtSet.add(newUserName);
            }
        });
        if (!CollectionUtils.isEmpty(newMatchedAtSet)) {
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.in("username",newMatchedAtSet);
            List<User> userDBOList = userMapper.selectList(userQueryWrapper);
            if (!CollectionUtils.isEmpty(userDBOList)) {
                atUserIdList.addAll(userDBOList.stream().map(User::getUserId).collect(Collectors.toSet()));
            }
        }
        return textContent;
    }
}




